/*
 * IGDao.java
 * Created on 16 juin 2007
 *
 * Glacéo Internet Platform
 * http://sourceforge.net/projects/chm/
 *
 * Copyright (c) 2005-2009, Jan and Jens Janke (VirtualHockey Project)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.hockeo.vhbase.data.dao;

import java.io.Serializable;
import java.util.List;
import java.util.Map;

import com.hockeo.vhbase.data.dao.assoc.GAssociation;
import com.hockeo.vhbase.data.dao.assoc.GNationalAssociation;
import com.hockeo.vhbase.data.dao.club.GClub;
import com.hockeo.vhbase.data.dao.club.GClubAbstractCupHistoryRecord;
import com.hockeo.vhbase.data.dao.club.GClubCupHistoryRecord;
import com.hockeo.vhbase.data.dao.club.GClubHistoryRecord;
import com.hockeo.vhbase.data.dao.club.GClubLeagueHistoryRecord;
import com.hockeo.vhbase.data.dao.club.GClubSeasonSummary;
import com.hockeo.vhbase.data.dao.contest.GContest;
import com.hockeo.vhbase.data.dao.contest.GContestElement;
import com.hockeo.vhbase.data.dao.contest.GContestHistoryRecord;
import com.hockeo.vhbase.data.dao.contest.GContestRound;
import com.hockeo.vhbase.data.dao.contest.GLeague;
import com.hockeo.vhbase.data.dao.contest.GNationalCup;
import com.hockeo.vhbase.data.dao.contest.GRoundRobinContestElement;
import com.hockeo.vhbase.data.dao.match.GKOMatch;
import com.hockeo.vhbase.data.dao.match.GMatch;
import com.hockeo.vhbase.data.dao.misc.GChart;
import com.hockeo.vhbase.data.dao.misc.GLanguage;
import com.hockeo.vhbase.data.dao.misc.GTranslation;
import com.hockeo.vhbase.data.dao.season.GMatchday;
import com.hockeo.vhbase.data.dao.season.GMoveday;
import com.hockeo.vhbase.data.dao.season.GSeason;
import com.hockeo.vhbase.data.dao.standings.GArchivedStandings;
import com.hockeo.vhbase.data.dao.standings.GECRStandings;
import com.hockeo.vhbase.data.dao.standings.GENRStandings;
import com.hockeo.vhbase.data.dao.standings.GFreeTicket;
import com.hockeo.vhbase.data.dao.standings.GGoalsAccount;
import com.hockeo.vhbase.data.dao.standings.GStandings;
import com.hockeo.vhbase.data.dao.user.GUser;
import com.hockeo.vhbase.data.helper.GArchivedStandingsType;
import com.hockeo.vhbase.data.helper.GChartType;
import com.hockeo.vhbase.data.helper.GContestHistoryType;
import com.hockeo.vhbase.data.helper.GContestRoundType;
import com.hockeo.vhbase.data.helper.GIntCupParticipant;
import com.hockeo.vhbase.data.helper.GMatchType;
import com.hockeo.vhbase.data.helper.GSortDir;
import com.hockeo.vhbase.data.helper.GStandingsRankType;
import com.hockeo.vhbase.data.helper.GStandingsType;
import com.hockeo.vhbase.error.GDataException;

/**
 * DAO for all persistent Glacéo objects.
 *
 * @version $Id$
 * @author jjanke
 */
public interface IGDao
{
  /**
   * Makes the given object persistent.
   *
   * @param object the object to be persisted in the application's database
   */
  public void makePersistent( Object object );

  /**
   * Deletes the given object from the persistent datastore.
   *
   * @param object the object to be deleted from the application's database
   */
  public void delete( Object object );

  /**
   * Removes the given object from the session of the underlying persistence layer.
   *
   * @param object the object to be evicted from the session
   */
  public void evict( Object object );

  /**
   * Deletes all entities of the given class type. To be used with great care! This method
   * requires to be executed within an already existing transaction. An isolated call is
   * not allowed.
   *
   * @param classEntity the class object representing the entity type for which all
   *          instances should be deleted
   */
  public <T> void deleteAll( Class<T> classEntity );

  /**
   * Deletes all goals accounts, matches, ko matches, free tickets and standings
   * associated to the given contest element. To be used with great care! This method
   * requires to be executed within an already existing transaction. An isolated call is
   * not allowed.
   *
   * @param element the contest element for which to delete attached data
   */
  public void deleteGoalAccountsMatchesFreeTicketsAndStandings( GContestElement element );

  /**
   * Deletes all standings attached to the given moveday. Only the standings attached to
   * the first matchday will not be deleted by this method.
   *
   * @param moveday the moveday for which to delete all standings
   */
  public void deleteStandings( GMoveday moveday );

  /**
   * Deletes all charts that become outdated when a new season starts or a new moveday has
   * been analyzed. Such charts usually refer to standings, rank evolutions etc.
   */
  public void deleteMovedayDependentCharts();

  /**
   * Deletes all archived eternal standings and all end of season standings from the
   * specified season.
   *
   * @param season the season for which to delete archived standings
   * @param contestElement the contest element for which to delete archived standings
   */
  public void deleteArchivedStandings( final GSeason season, final GContestElement contestElement );

  /**
   * Deletes all the data that is created at the end of a season (e.g. archived ECR/ENR
   * standings, club/season summaries etc.).
   *
   * @param season the season for which to delete the data
   */
  public void deleteEndOfSeasonData( final GSeason season );

  /**
   * Deletes all club/contest history records for the given season and contest.
   *
   * @param season the season for which to delete club history records
   * @param contest the contest for which history records should be deleted
   */
  public void deleteClubHistoryRecords( final GSeason season, final GContest contest );

  /**
   * Resets the league/club affiliation to its initial value. I.e. the league each club is
   * attached to is set to the league found in the first available club/league history
   * record for the given club.
   *
   * Be very careful when doing this operation! If the league structure has changed in
   * between (number of teams in one league, inconsistencies may appear).
   */
  public void resetClubLeagueAffiliations();

  /**
   * Sets the seedings for all clubs of the given association to 0.
   *
   * @param assoc the association for which to reset the seedings or null to reset the
   *          seedings of all clubs
   */
  public void resetClubSeedings( GAssociation assoc );

  /**
   * Convenience method for placing goals. This method is preferred over setting the goals
   * directly to a match if a lot of matches need to be processed simultaneously because
   * of a considerable gain in performance (the match with all its dependencies does not
   * need to be loaded).
   *
   * @param nMatchId the ID of the match for which goals need to be placed
   * @param nGoalsHome the amount of home goals to be placed or -1 to leave unchanged
   * @param nGoalsAway the amount of away goals to be placed of -1 to leave unchanged
   */
  public void placeGoalsToMatch( int nMatchId, int nGoalsHome, int nGoalsAway );

  /**
   * Resets all matches of the given moveday to their initial unplayed state.
   *
   * @param moveday the moveday for which all matches should be reset
   */
  public void resetMatches( GMoveday moveday );

  /**
   * Resets all KO matches of the given moveday to their initial unplayed state.
   *
   * @param moveday the moveday for which all KO matches should be reset
   */
  public void resetKOMatches( GMoveday moveday );

  /**
   * Archives all matches and deletes them afterwards. Any archived matches that are
   * attached to a season whose ID is less than the ID of the given season minus 4, is
   * also discarded.
   *
   * @param season the season for which to archive and delete all matches
   */
  public void archiveAndDeleteMatches( GSeason season );

  /**
   * Deletes all existing eternal standings for the given contest element and recreates
   * new ones afterwards based on all existing end of season standings.
   *
   * @param season the season which should be assigned to the created end of season
   *          eternal standings
   * @param element the contest element for which to create the standings
   * @return list of all created new eternal standings objects
   */
  public List<GArchivedStandings> createEternalStandings( GSeason season, GContestElement element );

  /**
   * Finds all persistent entities of the given Class.
   *
   * @param classEntityType the persistent class for which to return all persistent
   *          entities
   * @return a list of objects being instances of the specified persistent class
   */
  public <T> List<T> findAllEntities( Class<T> classEntityType );

  /**
   * Finds an entity by its identifier. Works with all persistent classes.
   *
   * @param classEntityType the persistent class for which to return an entity
   * @param entityId the unique key of the entity
   * @return the entity matching the ID or null if it is not found
   */
  public <T> T findEntity( Class<T> classEntityType, Serializable entityId );

  /**
   * Returns the number of finished seasons.
   *
   * @return the number of finished seasons
   */
  public long findNumFinishedSeasons();

  /**
   * Returns the current season. The current season is the only one which has the flag (
   * {@link GSeason#isActive()}) set to <code>true</code>.
   *
   * @return the current season
   * @throws GDataException when there is no current season
   */
  public GSeason findCurrentSeason() throws GDataException;

  /**
   * Returns the season that has been finished last. This can be but is not necessarily
   * the currently active season.
   *
   * @return the last finished season or <code>null</code> if there is none
   */
  public GSeason findLastFinishedSeason();

  /**
   * Returns the ID of the last finished season. This can be but is not necessarily the ID
   * of the currently active season.
   *
   * @return the ID of the last finished season or <code>null</code>
   */
  public Integer findLastFinishedSeasonId();

  /**
   * Returns a list of all seasons (up to the currently active one) ordered in descending
   * order by ID.
   *
   * @return a list of GSeason objects (the most recent season comes first)
   */
  public List<GSeason> findAllSeasons();

  /**
   * Returns a map of all seasons (up to the currently active one) ordered in descending
   * order by ID. The key of the map is the season id.
   *
   * @return a map of GSeason objects (the most recent season comes first)
   */
  public Map<Integer, GSeason> findAllSeasonsAsMap();

  /**
   * Returns a list containing all seasons (the same as {@link #findAllSeasons()} would
   * return). The value of the method {@link GSeason#isDataAvailable()} indicates whether
   * club/contest history data is available for a season or not.
   *
   * @param contest the contest for which to check data availability
   * @return a list of GSeason objects (the most recent season comes first)
   */
  public List<GSeason> findSeasonsForClubHistory( GContest contest );

  /**
   * Returns a list containing all seasons (the same as {@link #findAllSeasons()} would
   * return). The value of the method {@link GSeason#isDataAvailable()} indicates whether
   * international ranking data is available for a season or not.
   *
   * @return a list of GSeason objects (the most recent season comes first)
   */
  public List<GSeason> findSeasonsForIntRankings();

  /**
   * Returns all contest that take place in the given season.
   *
   * @param season the season for which to retrieve all active contests
   * @return list of contest objects
   */
  public List<GContest> findContestsForSeason( final GSeason season );

  /**
   * @return Returns a list of all movedays that are reserved (usable) for the given
   *         competition type. The results are ordered by moveday id (asc).
   */
  public List<GMoveday> findReservedMovedays( GContest contest );

  /**
   * Returns the current moveday.
   *
   * @return Returns the current moveday (the one to be played next) or returns
   *         <code>null</code> if the end of the season is reached or there is no active
   *         moveday yet.
   * @throws GDataException if more than one moveday is marked as being active
   */
  public GMoveday findCurrentMoveday() throws GDataException;

  /**
   * Returns the first moveday which is not marked as being executed.
   *
   * @return Returns the first non-executed moveday or <code>null</code> if all movedays
   *         have been executed.
   */
  public GMoveday findFirstNonExecutedMoveday();

  /**
   * Returns the last prepared moveday.
   *
   * @return Returns the ast prepared moveday or returns null if none has been prepared so
   *         far or there is no moveday at all.
   */
  public GMoveday findLastPreparedMoveday();

  /**
   * Returns the moveday during which the last matchday of the given contest element is
   * executed.
   *
   * @param element the contest element for which to determine the last moveday
   * @return the last moveday during which matches are played for the given contest
   *         element
   */
  public GMoveday findLastMoveday( GContestElement element );

  /**
   * Checks if all movedays of the season are executed. Returns <code>true</code> if there
   * is at least one moveday which is not marked as being executed.
   *
   * @return <code>true</code> if all movedays are marked as executed
   */
  public boolean areAllMovedaysExecuted();

  /**
   * Returns all matchdays attached to the given contest element.
   *
   * @param contestElement the contest element for which to retrieve the matchdays
   * @return list of matchdays
   */
  public List<GMatchday> findMatchdays( GContestElement contestElement );

  /**
   * Returns the first matchday that is associated with the given contest element.
   *
   * @param contestElement the contest element for which to retrieve the first matchday
   * @return the first matchday belonging to the given contest element
   * @throws GDataException if there is no matchday attached to the contest element
   */
  public GMatchday findFirstMatchday( final GContestElement contestElement ) throws GDataException;

  /**
   * Returns the last matchday that is associated with the given contest element.
   *
   * @param contestElement the contest element for which to retrieve the last matchday
   * @return the last matchday belonging to the given contest element
   * @throws GDataException if there is no matchday attached to the contest element
   */
  public GMatchday findLastMatchday( final GContestElement contestElement ) throws GDataException;

  /**
   * Returns the matchday with the given number for the specified contest element.
   *
   * @param contestElement the contest element for which to retrieve the matchday
   * @param nMatchdayNum the number of the requested matchday
   * @return the matchday with the given number of the specified contest element or
   *         <code>null</code> if there is none
   */
  public GMatchday findMatchday( GContestElement contestElement, int nMatchdayNum );

  /**
   * Determines the last executed matchday of the given contest element and returns it.
   * The last played matchday is determined by checking what is the last matchday marked
   * as being analysed.
   *
   * @param contestElement the contest element for which to return the last executed
   *          matchday
   * @return the last executed matchday or if no matchday has been executed so far, the
   *         first matchday is returned. If no matchday exists <code>null</code> is
   *         returned.
   */
  public GMatchday findLastPlayedMatchday( GContestElement contestElement );

  /**
   * Finds the last matchday of the moveday whose ID is specified.
   *
   * @param nMovedayId the ID of the moveday for which the last matchday should be
   *          retrieved
   * @param contestElement the contest element for which to retrieve the matchday
   * @return the last matchday of the moveday whose ID is specified or <code>null</code>
   *         if there was no matchday before the given moveday
   */
  public GMatchday findLastMatchdayBeforeMoveday( final GMoveday moveday, final GContestElement contestElement );

  /**
   * Returns the number of matches that exist for the given contest element.
   *
   * @param contestElement the contest element for which the number of matches is required
   * @return the total number of matches that exist for the given contest element
   */
  public long findNumMatches( final GContestElement contestElement );

  /**
   * Returns the number of goal accounts that exist for the given contest element.
   *
   * @param contestElement the contest element for which the number of goal accounts is
   *          required
   * @return the total number of goal accounts that exist for the given contest element
   */
  public long findNumGoalsAccounts( final GContestElement element );

  /**
   * Returns the number of all clubs currently registered in the database.
   */
  public long findNumClubs();

  /**
   * Returns the number of all clubs currently attached to a national league of the given
   * category.
   *
   * @param nCategory the category of the league for which the number of clubs is
   *          requested
   * @return the number of clubs for the given category
   */
  public long findNumClubs( final int nCategory );

  /**
   * Returns the number of all clubs being attached to the given association.
   *
   * @param assoc the association for which the number of clubs is requested
   * @return the number of clubs for the given association
   */
  public long findNumClubs( final GAssociation assoc );

  /**
   * Returns the number of clubs attached to the given association and to a league of the
   * given category.
   *
   * @param assoc the association for which the number of clubs is requested
   * @param nCategory the category of the league for which the number of clubs is
   *          requested
   * @return the number of clubs for the given association/category combination
   */
  public long findNumClubs( final GAssociation assoc, final int nCategory );

  /**
   * Returns a list of all matches attached to the given contest element.
   *
   * @param element the element for which to return matches
   * @return a list of matches
   */
  public List<GMatch> findMatches( GContestElement element );

  /**
   * Returns all matches that belong to the given moveday and for which one or both clubs
   * are managed by a specific user type (human or computer).
   *
   * @param moveday the moveday on which the searched matches are played
   * @param classUser the user type which is involved in the matches
   * @return a list of matches
   */
  public List<GMatch> findMatches( GMoveday moveday, Class<? extends GUser> classUser );

  /**
   * Returns all matches that belong to the given moveday and for which one or both clubs
   * are managed by a specific user type (human or computer).
   *
   * @param moveday the moveday on which the searched matches are played
   * @param classUser the user type which is involved in the matches
   * @return a map where the ID of the match is the key and the match the value
   */
  public Map<Integer, GMatch> findMatchesAsMap( GMoveday moveday, Class<? extends GUser> classUser );

  /**
   * Finds all matches the given club participates in within the also specified contest.
   *
   * @param club the club for which to seek matches
   * @param type the match type (HOME, AWAY, ALL)
   * @param contest the competition from which to take the matches
   * @return a list of the club's matches in the specified contest
   */
  public List<GMatch> findMatches( GClub club, GMatchType type, GContest contest );

  /**
   * Finds all matches the given club participates in in the current season.
   *
   * @param club the club for which to seek matches
   * @param type the match type (HOME, AWAY, ALL)
   * @return a list of the club's (already known) matches this season
   */
  public List<GMatch> findMatches( GClub club, GMatchType type );

  /**
   * Finds all matches the club partipates in within the specified contest element and
   * during the given moveday.
   *
   * @param club the club for which to lookup matches
   * @param element the contest element in which the matches take place
   * @param moveday the moveday during which the matches are played
   * @return a list containing all matches for the specified criteria
   */
  public List<GMatch> findMatches( GClub club, GContestElement element, GMoveday moveday );

  /**
   * Finds all the KO matches that are attached to the given contest. All matches that are
   * not KO matches are ignored.
   *
   * @param contest the contest for which to return all the KO matches
   * @return a list of KO matches ordered in descending order of the round the matches are
   *         attached to
   */
  public List<GKOMatch> findAllKOMatches( GContest contest );

  /**
   * Returns all goal accounts that exist for the given contest element.
   *
   * @param contestElement the contest element for which to retrieve the goal accounts
   * @return list of goal accounts
   */
  public List<GGoalsAccount> findGoalsAccounts( GContestElement contestElement );

  /**
   * Returns all goal accounts that exist for the given contest element in a map where the
   * clubs the goal account are associated with are the keys.
   *
   * @param contestElement the contest element for which to retrieve the goal accounts
   * @return map of club/goal accounts
   */
  public Map<GClub, GGoalsAccount> findGoalsAccountsAsMap( GContestElement contestElement );

  /**
   * Returns a map with two entries which are the goal accounts for the two clubs that
   * participate in the given match.
   *
   * @param match the match for whose participating clubs to retrieve goal accounts
   * @return map of club/goal accounts
   */
  public Map<GClub, GGoalsAccount> findGoalsAccountsForMatch( GMatch match );

  /**
   * Returns all leagues that are linked to the given country.
   *
   * @param strCountry the ID of the association for which to retrieve all existing
   *          leagues
   * @return the list of leagues for the given association
   */
  public List<GLeague> findLeaguesForAssociation( String strAssociationId );

  /**
   * Returns all leagues of the given association that have the specified category.
   *
   * @param assoc the association for which to look up the leagues
   * @param nCategory the required league category
   * @return list of matching leagues
   */
  public List<GLeague> findLeagues( GAssociation assoc, int nCategory );

  /**
   * Returns the national cup competition that is linked to the given country.
   *
   * @param strCountry the ID of the association for which to retrieve the cup contest
   * @return the cup contest for the given association or <code>null</code> if there is
   *         none
   * @throws GDataException if more than one cup competition is found
   */
  public GNationalCup findCupForAssociation( String strAssociationId ) throws GDataException;

  /**
   * Returns all top level leagues from the national associations. The leagues are ordered
   * by the ID of the association they belong to.
   *
   * @return list of all top level leagues
   */
  public List<GLeague> findTopNationalLeagues();

  /**
   * Finds all clubs that have been promoted in the specified season.
   *
   * @param assoc the association for which to find promoted clubs
   * @param season the season in which the promotions have been earned
   * @return a list containing all promoted clubs of the association regardless of their
   *         league categories
   */
  public List<GClub> findPromotedClubs( final GAssociation assoc, final GSeason season );

  /**
   * Finds all clubs that have been promoted in the specified season.
   *
   * @param assoc the association for which to find promoted clubs
   * @param season the season in which the promotions have been earned
   * @return a map containing all promoted clubs of the association grouped by league
   *         category
   */
  public Map<Integer, List<GClub>> findPromotedClubsAsMap( final GAssociation assoc, final GSeason season );

  /**
   * Finds all clubs that have been relegated in the specified season.
   *
   * @param assoc the association for which to find relegated clubs
   * @param season the season in which the relegations have occured
   * @return a list containing all relegated clubs of the association regardless of their
   *         league categories
   */
  public List<GClub> findRelegatedClubs( final GAssociation assoc, final GSeason season );

  /**
   * Finds all clubs that have been relegated in the specified season.
   *
   * @param assoc the association for which to find relegated clubs
   * @param season the season in which the relegations have occured
   * @return a map containing all relegated clubs of the association grouped by league
   *         category
   */
  public Map<Integer, List<GClub>> findRelegatedClubsAsMap( final GAssociation assoc, final GSeason season );

  /**
   * Returns all clubs from the given association that are attached to a league of which
   * the category is in the given interval.
   *
   * @param assoc the association for which to retrieve clubs
   * @param nCatFrom the start category
   * @param nCatTo the end category
   * @return unordered list of clubs belonging to the given association and to a league
   *         whose category is in the specified interval
   */
  public List<GClub> findClubsForLeagueCategories( GAssociation assoc, int nCatFrom, int nCatTo );

  /**
   * Returns all the clubs that should participate in this season's Champions League
   * season. The list is ordered in ascending seeding order. The seeding order is
   * established according to their ECR points at the end of the previous season.
   *
   * @param seasonCurrent current season
   * @return list of participants
   */
  public List<GIntCupParticipant> findClubsForChampionsLeague( GSeason seasonCurrent );

  /**
   * Returns the number of clubs that is initially qualified for the Champions League in
   * the current season.
   *
   * @param seasonCurrent current season
   * @return number of champion's league participants
   */
  public long findNumChampionsLeagueParticipants( GSeason seasonCurrent );

  /**
   * Returns all the clubs that should participate in this season's World League season.
   * The list is ordered in ascending seeding order.
   *
   * @param seasonCurrent current season
   * @return list of participants
   */
  public List<GIntCupParticipant> findClubsForWorldLeague( GSeason seasonCurrent );

  /**
   * Returns all clubs from the given association for which no league standings have been
   * recorded in the given season.
   *
   * @param assoc the association for which to retrieve clubs
   * @param season the season for which to retrieve clubs
   * @return list of clubs not having participated in a national league contest in the
   *         specified season
   */
  public List<GClub> findClubsNotPlayingInLeagueContest( GAssociation assoc, GSeason season );

  /**
   * Returns all clubs that have been participated in the standard league contests of the
   * given association in the official seeding order (i.e. national champion first, worst
   * team of all lowest category leagues last). Clubs that have not participated in the
   * specified season are ignored.
   *
   * @param assoc the association for which to retrieve clubs
   * @param season the season for which to retrieve clubs
   * @return list of clubs in seeding order (obtained from the archived end of season
   *         league standings)
   */
  public List<GClub> findClubsInSeedingOrder( GAssociation assoc, GSeason season );

  /**
   * Returns all clubs that are currently attached to the given contest element. The link
   * is resolved by analysing the goal accounts for the given contest element.
   *
   * @param contestElement the contest element for which to retrieve the participating
   *          clubs
   * @return list of clubs participating in the given contest element
   */
  public List<GClub> findClubsForContestElement( GContestElement contestElement );

  /**
   * Returns all clubs that are currently affiliated to the league whose ID is given.
   *
   * @param strLeagueId the ID of the league for which to retrieve clubs
   * @return list of clubs affiliated to the given league
   */
  public List<GClub> findClubsForLeague( String strLeagueId );

  /**
   * Returns all clubs that are currently attached to the specified national or
   * international cup round. Works for all contests that use a club/history
   * implementation that is a sub class of {@link GClubAbstractCupHistoryRecord}.
   *
   * @param season the season for which to retrieve the clubs
   * @param round the round for which to return affiliated clubs
   * @param fOrderBySeeding if <code>true</code> the clubs are ordered in ascencing order
   *          according to the value of the seeding field, otherwise the clubs are ordered
   *          alphabetically. If <code>true</code> and the round is a round after the main
   *          round, the clubs are ordered according to the number of ECR points so far
   *          obtained
   * @return list of clubs currently affiliated to the given cup round
   */
  public List<GClub> findClubsForCupRound( GSeason season, GContestRound round, boolean fOrderBySeeding );

  /**
   * Returns all club/league history records for the given season and association where
   * something "special" happened. I.e. only those records where a team was promoted,
   * qualified for a European cup or relegated are returned.
   *
   * @param season the season for which to return the records
   * @param assoc the association for which to return the records
   * @return a list of club/league history records for all leagues of the given
   *         association and season. The results are ordered by contest category, contest
   *         ID and rank (all ascending).
   */
  public List<GClubLeagueHistoryRecord> findSpecialClubLeagueHistoryRecords( GSeason season, GNationalAssociation assoc );

  /**
   * Returns the first non played contest round of the given contest.
   *
   * @param contest the contest for which to retrieve the first non played contest round
   * @return the first non-played contest round or <code>null</code> if all rounds have
   *         been played
   */
  public GContestRound findFirstNonPlayedContestRound( final GContest contest );

  /**
   * Returns all free tickets ("laissez-passer") for the given contest round. A free
   * ticket means that the ticket holding club advances to the next round "for free"
   * without playing a match.
   *
   * @param round the round for which to retrieve free tickets
   * @return list of free tickets awarded for the given contest round
   */
  public List<GFreeTicket> findFreeTickets( GContestRound round );

  /**
   * Determines the current contest round and returns it. This method first searches for
   * the round which is in progress. If one is found, it is returned. Otherwise, the last
   * played round is returned. If no round is in progress and none has been finished
   * neither, the first round is returned.
   *
   * @param contest the contest for which to determine the current round
   * @return the current contest round or null if there is no contest round defined for
   *         the current season
   */
  public GContestRound findCurrentContestRound( GContest contest );

  /**
   * Returns all contest elements for which matchdays are organized at the given moveday
   * for the given club.
   *
   * @param moveday the moveday for which active contest elements should be returned
   * @param club the club for which the contest elements should be returned, if it is
   *          involved in at least one match at the given moveday
   * @return list of active contest elements
   */
  public List<GContestElement> findContestElements( GMoveday moveday, GClub club );

  /**
   * Finds a club history record for a particular club/contest/season combination.
   *
   * @param classRecordType the actual type of club history to be retrieved
   * @param contest the contest for which to retrieve the history object
   * @param season the season for which to retrieve the history object
   * @param club the club whose history is requested for the particular contest and season
   * @return the matching club history object or <code>null</code> if there is none
   */
  public <T extends GClubHistoryRecord> T findClubHistoryRecord( final Class<T> classRecordType,
      final GContest contest, final GSeason season, final GClub club );

  /**
   * Finds a club history record for a particular club/season combination. This method
   * assumes that a club can only have one instance of each club/history type per season.
   *
   * @param classRecordType the actual type of club history to be retrieved
   * @param season the season for which to retrieve the history object
   * @param club the club whose history is requested for the particular contest and season
   * @return the matching club history object or <code>null</code> if there is none
   */
  public <T extends GClubHistoryRecord> T findClubHistoryRecord( final Class<T> classRecordType, final GSeason season,
      final GClub club );

  /**
   * Returns all club history records for the given season and association where the
   * number of awarded ECR points is greater than 0.
   *
   * @param season the season for which to retrieve the records
   * @param assoc the association for which to retrieve club history records
   * @return a list of {@link GClubHistoryRecord} instances having more than 0 ECR points
   */
  public List<GClubHistoryRecord> findClubHistoryRecordsForECR( GSeason season, GNationalAssociation assoc );

  /**
   * Returns all club history elements for the given contest type (all contests of the
   * specified type) which concern clubs between the given ranks.
   *
   * @param classRecordType the actual type of club history to be retrieved
   * @param season the season for which to retrieve the history records
   * @param nFirstRank the first rank to be retrieved
   * @param nLastRank the last rank to be retrieved
   * @return a list of matching club/history records ordered ascendingly by rank
   */
  public <T extends GClubHistoryRecord> List<T> findClubHistoryRecordByRank( final Class<T> classRecordType,
      final GSeason season, final int nFirstRank, final int nLastRank );

  /**
   * Returns all club history elements for the given contest which concern clubs between
   * the given ranks.
   *
   * @param contest the contest for which to retrieve history records
   * @param season the season for which to retrieve the history records
   * @param nFirstRank the first rank to be retrieved
   * @param nLastRank the last rank to be retrieved
   * @return a list of matching club/history records ordered ascendingly by rank
   */
  public List<GClubHistoryRecord> findClubHistoryRecordsByRank( final GContest contest, final GSeason season,
      final int nFirstRank, final int nLastRank );

  /**
   * Returns all club history records for the clubs that have been involved in the given
   * contest element.
   *
   * @param classClubContestHistory the concrete subclass of {@link GClubHistoryRecord}
   *          for which instances are requested
   * @param season the season for which to retrieve the CHRs
   * @param element the contest element for which to retrieve the records
   * @return a map in which the history records for all involved clubs are included, the
   *         exact type of club history records depends on the contest type (i.e. for a
   *         league {@link GClubLeagueHistoryRecord} instances are returned, for a cup
   *         {@link GClubCupHistoryRecord} instances etc.
   */
  public <T extends GClubHistoryRecord> Map<GClub, T> findClubHistoryRecordsByContestElement(
      final Class<T> classClubContestHistory, final GSeason season, GContestElement element );

  /**
   * Returns a list of all club history objects for the given season and association.
   *
   * @param classRecordType concrete sub class of {@link GClubHistoryRecord} in order to
   *          only retrieve objects for a certain contest type
   * @param assoc the association for which to retrieve the objects
   * @param season the season for which to retrieve the history objects
   * @return a list of matching club history records
   */
  public <T extends GClubHistoryRecord> List<T> findClubHistoryRecords( Class<T> classRecordType,
      final GNationalAssociation assoc, final GSeason season );

  /**
   * @see #findClubHistoryRecords(Class, GNationalAssociation, GSeason)
   * @return a map in which the history records for all clubs of the given association are
   *         included
   */
  public <T extends GClubHistoryRecord> Map<GClub, T> findClubHistoryRecordsAsMap( Class<T> classRecordType,
      final GNationalAssociation assoc, final GSeason season );

  /**
   * Retrieves all club history records of the given type for the given contest and
   * season.
   *
   * @param classRecordType the class indicating the history type to be retrieved
   * @param contest the contest for which to retrieve the contest history records
   * @param season the season for which to retrieve the history records
   * @return list of retrieved history records ordered descendingly by season
   */
  public <T extends GClubHistoryRecord> List<T> findClubHistoryRecords( final Class<T> classRecordType,
      final GContest contest, final GSeason season );

  /**
   * Retrieves all club history records of the given type that exist for the specified
   * club.
   *
   * @param classRecordType the class indicating the history type to be retrieved
   * @param club the club for which to retrieve all existing history records
   * @return list of retrieved history records ordered descendingly by season
   */
  public <T extends GClubHistoryRecord> List<T> findClubHistoryRecords( final Class<T> classRecordType, final GClub club );

  /**
   * Retrieves all season summary objects that exist for the specified club.
   *
   * @param club the club for which to retrieve the season summary objects
   * @return list of matching season summary records ordered descendingly by season
   */
  public List<GClubSeasonSummary> findClubSeasonSummaries( final GClub club );

  /**
   * Returns all club/season summaries where:
   *
   * <ul>
   * <li>the league rank is 1 OR</li>
   * <li>the league rank type is {@link GStandingsRankType#PROMOTED_1} or
   * {@link GStandingsRankType#PROMOTED_2} or {@link GStandingsRankType#RELEGATED} OR</li>
   * <li>the cup reached round equals {@link GContestRoundType#WINNER}</li>
   * </ul>
   *
   * @return list with the matching records in random (undefined) order
   */
  public List<GClubSeasonSummary> findClubSeasonSummariesForClubStats();

  /**
   * Returns all contest history records for the given season and type.
   *
   * @param season the season for which to retrieve the records
   * @param type the history type which is requested
   * @return list of matching GContestHistoryRecord objects
   */
  public List<GContestHistoryRecord> findContestHistoryRecords( final GSeason season, final GContestHistoryType type );

  /**
   * Returns all history records of the major international and national contests (CL,WL,
   * national league and cup) in the given season.
   *
   * @param season the season for which to return the contest history records
   * @return list of contest history records
   */
  public List<GContestHistoryRecord> findMajorContestHistoryRecords( final GSeason season );

  /**
   * Returns all contest history records matching the given contest. The list is ordered
   * by season in descending (i.e. the last winner comes first) order.
   *
   * @param contest the contest for which to retrieve the contest history
   * @return list of {@link GContestHistoryRecord} objects
   */
  public List<GContestHistoryRecord> findContestHistoryRecords( final GContest contest );

  /**
   * Returns the contest history record for the given season and contest.
   *
   * @param season the season for which to retrieve the contest history record
   * @param contest the contest for which to retrieve the history record
   * @return the found record or <code>null</code> if there is none
   * @throws GDataException if there is more than one record registered for the given
   *           season/contest combination
   */
  public GContestHistoryRecord findContestHistoryRecord( final GSeason season, final GContest contest )
      throws GDataException;

  /**
   * Returns the ENR standing for the given association and season.
   *
   * @param season the season for which to retrieve the standings
   * @param assoc the association for which to retrieve the standings
   * @return the matching ENR standings object or <code>null</code> if there is none
   */
  public GENRStandings findENRStanding( final GSeason season, final GNationalAssociation assoc );

  /**
   * Returns all ENR standings for the given season.
   *
   * @param season the season for which to retrieve the standings
   * @return the corresponding ENR standings objects
   */
  public List<GENRStandings> findENRStandings( final GSeason season );

  /**
   * Retrieves the latest existing ECR standings object for the specified club.
   *
   * @param club the club for which to retrieve the latest ECR standings object
   * @return the matching GECRStandings object or <code>null</code> if there is none
   */
  public GECRStandings findECRStandings( final GClub club );

  /**
   * Returns all ECR standings of all clubs being member of the given national association
   * for the specified season.
   *
   * @param season the season for which to retrieve the standings
   * @param assoc the association for which to retrieve the standings
   * @return list of matching ECR standings ordered ascendingly by rank
   */
  public List<GECRStandings> findECRStandings( final GSeason season, final GNationalAssociation assoc );

  /**
   * Returns all ECR standings of all clubs being member of the given national association
   * for the specified season.
   *
   * @param season the season for which to retrieve the standings
   * @param assoc the association for which to retrieve the standings
   * @return map in which each club of the given association is mapped to its respective
   *         ECR standings
   */
  public Map<GClub, GECRStandings> findECRStandingsAsMap( final GSeason season, final GNationalAssociation assoc );

  /**
   * Returns ECR standings ordered by rank for the given season starting with the one
   * indicated by the second parameter. The total amount of returned rankings depends on
   * the third parameter.
   *
   * @param season the season for which to retrieve the standings
   * @param nFirst the first standing to be retrieved (ordered by rank)
   * @param nAmount the amount of standings to be returned
   * @return list of standings matching the input criteria
   */
  public List<GECRStandings> findECRStandings( final GSeason season, final int nFirst, final int nAmount );

  /**
   * Retrieves ECR standings for the given season with support for paging and database
   * controlled ordering.
   *
   * @param season the season for which to return the ECR standings
   * @param assoc <code>null</code> to display teams of all associations or an association
   *          to only display the teams of a particular association
   * @param strSortField the name of the field by which to sort (the name must correspond
   *          to the name of a getter method inside of {@link GECRStandings} without the
   *          prefix 'get' or 'is' and with the first letter in lower case)
   * @param sortDir the desired sorting direction
   * @param nOffset the initial offset (only get results as from ...)
   * @param nLimit the maximum number of results to return
   * @return a list of ECR standings
   */
  public List<GECRStandings> findECRStandings( GSeason season, GNationalAssociation assoc, String strSortField,
      GSortDir sortDir, int nOffset, int nLimit );

  /**
   * Returns how many archived standings exist for the given arguments.
   *
   * @param type the archive type (season or eternal standings)
   * @param season the season the standings are for or null for eternal standings
   * @param contestElement the contest element the archived standings are requested for
   * @return number of archived standings matching the given criteria
   */
  public long findNumArchivedStandings( GArchivedStandingsType type, GSeason season, GContestElement contestElement );

  /**
   * Returns the number of ECR standings available in the given season.
   *
   * @param season the season for which the ECR standings are requested
   * @param assoc if not <code>null</code>, only the standings for all the teams of the
   *          given association are counted, otherwise all
   * @return the total number of ECR standings available for the given season
   */
  public long findNumECRRankings( GSeason season, GNationalAssociation assoc );

  /**
   * Finds all archived standings of the given type for the indicated season (may be null
   * if eternal standings are requested). All standings regardless of their type (HOME,
   * AWAY, TOTAL etc.) will be returned by this method.
   *
   * @param type the archive type (season or eternal standings)
   * @param season the season the standings are for or null for eternal standings
   * @param contestElement the contest element the archived standings are requested for
   * @return a list of matching standings
   */
  public List<GArchivedStandings> findArchivedStandings( final GArchivedStandingsType type, final GSeason season,
      final GContestElement contestElement );

  /**
   * Finds all archived standings of the given type for the indicated season (may be null
   * if eternal standings are requested).
   *
   * @param type the archive type (season or eternal standings)
   * @param season the season the standings are for or null for eternal standings
   * @param contestElement the contest element the archived standings are requested for
   * @param standingsType the type of standings to be retrieved
   * @return a list of matching standings
   */
  public List<GArchivedStandings> findArchivedStandings( final GArchivedStandingsType type, final GSeason season,
      final GContestElement contestElement, final GStandingsType standingsType );

  /**
   * Finds all archived standings of the given type for the indicated season (may be null
   * if eternal standings are requested).
   *
   * @param type the archive type (season or eternal standings)
   * @param season the season the standings are for or null for eternal standings
   * @param contestElement the contest element the archived standings are requested for
   * @return a map where each found standing is mapped to a club
   */
  public Map<GClub, GArchivedStandings> findArchivedStandingsAsMap( final GArchivedStandingsType type,
      final GSeason season, final GContestElement contestElement );

  /**
   * Retrieves eternal standings for the given contest element with support for paging and
   * database controlled ordering.
   *
   * @param element the contest element for which to retrieve standings
   * @param strSortField the name of the field by which to sort (the name must correspond
   *          to the name of a getter method inside of {@link GArchivedStandings} without
   *          the prefix 'get' or 'is' and with the first letter in lower case)
   * @param sortDir the desired sorting direction
   * @param nOffset the initial offset (only get results as from ...)
   * @param nLimit the maximum number of results to return
   * @return a list of archived standings
   */
  public List<GArchivedStandings> findEternalStandings( GContestElement element, String strSortField, GSortDir sortDir,
      int nOffset, int nLimit );

  /**
   * Returns all standings for the given club up to the given matchday and for the contest
   * element attached to the specified matchday.
   *
   * @param club the club for which to retrieve the standings
   * @param matchday the matchday up to which the standings shall be retrieved
   * @param type the standings type
   * @return a list of standings ordered by matchday number
   */
  public List<GStandings> findStandings( GClub club, GMatchday matchday, GStandingsType type );

  /**
   * Returns all standings for the given matchday and type.
   *
   * @param matchday the matchday for which to retrieve the standings
   * @param type the type of the standings (TOTAL, HOME, AWAY)
   * @return a list of standings for the given type/matchday combination
   * @throws GDataException if there is a data inconsistency
   */
  public List<GStandings> findStandings( GMatchday matchday, GStandingsType type ) throws GDataException;

  /**
   * Returns a map containing the latest TOTAL, HOME and AWAY standings for the given club
   * in the specified contest element.
   *
   * This method returns the standings from the last matchday of the last executed
   * moveday! I.e. even if standings for matchdays exist that belong to a moveday not
   * (yet) marked as being executed, this method may not return the correct data!
   *
   * @param club the club for which to retrieve the standings
   * @param element the round robin contest element from which to retrieve the standings
   * @return a map where the standings type is the key
   * @throws GDataException if there is a data inconsistency
   */
  public Map<GStandingsType, GStandings> findCurrentStandings( GClub club, GRoundRobinContestElement element )
      throws GDataException;

  /**
   * Returns the latest (current) standings for the given type/club/element combination.
   *
   * This method returns the standings from the last matchday of the last executed
   * moveday! I.e. even if standings for matchdays exist that belong to a moveday not
   * (yet) marked as being executed, this method may not return the correct data!
   *
   * @param type the requested standings type
   * @param club the club for which to retrieve the standings
   * @param element the round robin contest element from which to retrieve the standings
   * @return the matching standings object
   * @throws GDataException if there is more than one matching standings object
   */
  public GStandings findCurrentStandings( GStandingsType type, GClub club, GRoundRobinContestElement element )
      throws GDataException;

  /**
   * Returns a list with the latest standings of all clubs in the given contest element.
   * This method returns all standings it can find of all types (incl. HOME/AWAY/TOTAL).
   *
   * @param element the round robin contest element from which to retrieve the standings
   * @return a list of all standings (regardless of their types) for all clubs in the
   *         contest element
   * @throws GDataException
   */
  public List<GStandings> findCurrentStandings( final GRoundRobinContestElement element ) throws GDataException;

  /**
   * Finds the final standings of the contest element for the current season. The returned
   * list is ordered at first in descending order of the standings type (TOTAL, then HOME
   * and finally AWAY) and then by rank in ascending order. I.e. the first standings
   * object corresponds to the total standings of the contest element winner.
   *
   * @param element the round robin contest element from which to retrieve the standings
   * @return a list of all standings (regardless of their types) for all clubs in the
   *         contest element
   * @throws GDataException if there is a data inconsistency or if there is no matching
   *           standing (because e.g. the season is not yet finished)
   */
  public List<GStandings> findFinalStandings( final GRoundRobinContestElement element ) throws GDataException;

  /**
   * Finds the final standings of the contest element for the current season. The returned
   * list is ordered by rank in ascending order.
   *
   * @param element the round robin contest element from which to retrieve the standings
   * @param type the required standings type
   * @return a list of all standings (regardless of their types) for all clubs in the
   *         contest element
   * @throws GDataException if there is a data inconsistency or if there is no matching
   *           standing (because e.g. the season is not yet finished)
   */
  public List<GStandings> findFinalStandings( final GRoundRobinContestElement element, final GStandingsType type )
      throws GDataException;

  /**
   * Returns a list with the latest standings of all clubs in the given contest element.
   *
   * This method returns the standings from the last matchday of the last executed
   * moveday! I.e. even if standings for matchdays exist that belong to a moveday not
   * (yet) marked as being executed, this method may not return the correct data!
   *
   * @param type the type of standings to retrieve
   * @param element the round robin contest element from which to retrieve the standings
   * @return a list of standings of the given type
   * @throws GDataException if there is a data inconsistency
   */
  public List<GStandings> findCurrentStandings( GStandingsType type, GRoundRobinContestElement element )
      throws GDataException;

  /**
   * Finds the latest standings for the given contest element in the specified rank
   * interval. This method only returns results if at least one matchday has been played
   * in the given contest element.
   *
   * @param type the standings type to be retrieved
   * @param element the element for which to retrieve the standings
   * @param nStartRank the start rank of the desired rank interval
   * @param nEndRank the end rank of the desired rank interval
   * @return a list of standings matching the given criteria (the list is ordered
   *         ascendingly by rank)
   * @throws GDataException if it is impossible to determine the last played matchday
   */
  public List<GStandings> findCurrentStandings( final GStandingsType type, final GContestElement element,
      final int nStartRank, final int nEndRank ) throws GDataException;

  /**
   * Finds all the standings objects attached to the given contest round and belonging to
   * the matchdays with the specified number. Only those standings where the rank is in
   * the specified range are returned.
   *
   * @param round the contest round for which to retrieve the standings
   * @param type the required standings type
   * @param nMatchdayNum the number of the matchday for which to retrieve the standings
   * @param nStartRank the start rank of the desired rank interval
   * @param nEndRank the end rank of the desired rank interval
   * @return the corresponding standings ordered by rank
   * @throws GDataException
   */
  public List<GStandings> findStandings( final GContestRound round, final GStandingsType type, final int nMatchdayNum,
      final int nStartRank, final int nEndRank ) throws GDataException;

  /**
   * Finds all the current standings objects attached to the given contest round. Only
   * those standings where the rank is in the specified range are returned.
   *
   * @param round the contest round for which to retrieve the standings
   * @param type the required standings type
   * @param nStartRank the start rank of the desired rank interval
   * @param nEndRank the end rank of the desired rank interval
   * @return the corresponding standings ordered by rank
   * @throws GDataException
   */
  public List<GStandings> findCurrentStandings( final GContestRound round, final GStandingsType type,
      final int nStartRank, final int nEndRank ) throws GDataException;

  /**
   * Finds all the final standings objects attached to the given contest round. Only those
   * standings where the rank is in the specified range are returned.
   *
   * @param round the contest round for which to retrieve the standings
   * @param type the required standings type
   * @param nStartRank the start rank of the desired rank interval
   * @param nEndRank the end rank of the desired rank interval
   * @return the corresponding standings ordered by rank
   * @throws GDataException
   */
  public List<GStandings> findFinalStandings( final GContestRound round, final GStandingsType type,
      final int nStartRank, final int nEndRank ) throws GDataException;

  /**
   * Retrieves the chart with the given type. Which arguments need to be supplied depends
   * on the chart type. Arguments that are not needed can be left empty.
   *
   * @param type the chart type to be retrieved
   * @param club the club for which to retrieve the chart (if applicable, otherwise null)
   * @param matchday the matchday for which to retrieve the chart (if applicable,
   *          otherwise null)
   * @return the found chart or null if there is none
   * @throws GDataException if there is more than one chart matching the given criteria
   */
  public GChart findChart( final GChartType type, final GClub club, final GMatchday matchday ) throws GDataException;

  /**
   * Returns the language that is marked as being the default language.
   *
   * @return the default language or <code>null</code> if there is none
   * @throws GDataException if there is more than one default language
   */
  public GLanguage findDefaultLanguage() throws GDataException;

  /**
   * Returns the translation for the given code.
   *
   * @param strCode the text to be translated
   * @param strLanguage the language (two letter lower case ISO language code)
   * @return the matching translation or <code>null</code> if there is none
   */
  public GTranslation findTranslation( String strCode, String strLanguage );
}
